package com.lzx.applib.okhttp.download;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.lzx.applib.utils.LogUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.OkHttpClient;

/**
 * Created by Lzx on 16/11/28 0028.
 */
public class DownloadTaskManager {
    public static final String TAG = "DownloadTaskManager";

    static DownloadTaskManager instance;

    public static DownloadTaskManager getInstance(Context context) {
        if (instance == null) {
            synchronized (DownloadTaskManager.class) {
                if (instance == null) {
                    instance = new DownloadTaskManager(context.getApplicationContext());
                }
            }
        }
        return instance;
    }

    private OkHttpClient client;
    private Map<String, List<ProgressListener>> listenerMap;
    private DownloadTask currentTask = null;
    private Handler mainLooperHandler = new Handler(Looper.getMainLooper());

    private DownloadTaskManager(Context context) {
        this.client = getProgressClient();
        listenerMap = new HashMap<>();
    }

    public synchronized void start() {
        LogUtil.d(TAG, "start");
        if (currentTask != null) return;

        DownloadInfo info = DownloadInfoTable.getInstance().getNextDownloadInfo();
        if (info != null) {
            LogUtil.d(TAG, "start2");
            currentTask = new DownloadTask(client, info, listener);
            currentTask.start();
        }
    }

    public void pause() {
        LogUtil.d(TAG, "pause");
        if (currentTask != null) {
            LogUtil.d(TAG, "pause2");
            currentTask.stop();
//            currentTask = null;
        }
    }

    public void addDownloadTask(DownloadInfo info) {
        DownloadInfoTable.getInstance().add(info);
        start();
    }

    public void startDownloadTask(DownloadInfo info) {
        LogUtil.d(TAG, "startDownloadTask");
        info.state = DownloadInfo.WAITING;
        DownloadInfoTable.getInstance().updateState(info);
        start();
    }

    public void pauseDownloadTask(DownloadInfo info) {
        LogUtil.d(TAG, "pauseDownloadTask1");
        info.state = DownloadInfo.PAUSE;
        DownloadInfoTable.getInstance().updateState(info);
        if (currentTask != null && currentTask.getDownloadInfo().equals(info)) {
            LogUtil.d(TAG, "pauseDownloadTask2");
            pause();
//            start();
        }
    }

    public void removeDownloadTask(DownloadInfo info) {
        DownloadInfoTable.getInstance().delete(info);
        if (currentTask != null && currentTask.getDownloadInfo().equals(info)) {
            pause();
//            start();
        }
    }

    private OkHttpClient getProgressClient() {
        return new OkHttpClient();
    }

    public void addListener(DownloadInfo task, ProgressListener listener) {
        List<ProgressListener> listeners = getListeners(task);
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    public void removeListener(DownloadInfo task, ProgressListener listener) {
        List<ProgressListener> listeners = getListeners(task);
        if (listeners.contains(listener)) {
            listeners.remove(listener);
        }
    }

    private List<ProgressListener> getListeners(DownloadInfo task) {
        if (task != null) {
            List<ProgressListener> listeners = listenerMap.get(task.remotePath);
            if (listeners == null) {
                listeners = Collections.synchronizedList(new ArrayList<ProgressListener>());
                listenerMap.put(task.remotePath, listeners);
            }
            return listeners;
        } else {
            return null;
        }
    }

    private ProgressListener listener = new ProgressListener() {
        long lastTime = System.currentTimeMillis();
        @Override
        public void update(final long totalBytes, final long doneByte) {
            if (System.currentTimeMillis() - lastTime > 1000) {
                LogUtil.d(TAG, "updateProgress() called with:", totalBytes, doneByte);
                lastTime = System.currentTimeMillis();
            }

            if (currentTask != null) {
                final DownloadInfo info = currentTask.getDownloadInfo();
                mainLooperHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        List<ProgressListener> listeners = getListeners(info);
                        for (int i = 0; i < listeners.size(); i++) {
                            listeners.get(i).update(totalBytes, doneByte);
                        }
                    }
                });
            }
        }

        @Override
        public void updateState(@DownloadInfo.TaskState final int state) {

            if (currentTask != null) {
                LogUtil.d(TAG, "updateState() called with:", state);
                final DownloadInfo info = currentTask.getDownloadInfo();
                mainLooperHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        List<ProgressListener> listeners = getListeners(info);
                        for (int i = 0; i < listeners.size(); i++) {
                            listeners.get(i).updateState(state);
                        }
                    }
                });
            }

            switch (state) {
                case DownloadInfo.ERROR:
                case DownloadInfo.FINISH:
                case DownloadInfo.PAUSE:
                    currentTask = null;
                    start();
                    break;
            }
        }
    };
}
